pico_8fandomcom-20200213-history
P8PNGFileFormat
PICO-8 can save cartridges in two file formats: the .p8 format, and the .p8.png format. The save command will use the format that corresponds to the filename extension. The .p8.png format is a binary format based on the PNG image format. A .p8.png file is an image that can be viewed in any image viewer (such as a web browser). The image appears as the picture of a game cartridge. PICO-8 generates this image using the most recent screenshot taken when pressing the F7 key while the cart is running. If the first two lines of Lua code are comments (a title and byline), it also puts the text of these comments on the label image. The cart data is stored using a stegonographic process. Each PICO-8 byte is stored as the two least significant bits of each of the four color channels, ordered ARGB (E.g: the A channel stores the 2 most significant bits in the bytes). The image is 160 pixels wide and 205 pixels high, for a possible storage of 32,800 bytes. Of these, only the first 32,773 bytes are used. Graphics and sound Bytes 0x0000-0x42ff are the spritesheet, map, flags, music, and sound effects data. These are copied directly into memory when the cart runs. See Memory for a complete explanation of the order and format of this data. Lua code Bytes 0x4300-0x7fff are the Lua code. If the first four bytes (0x4300-0x4303) are :c: followed by a null (\x00), then the code is stored as compressed data. Otherwise the code is stored as plaintext (ASCII), up to the first null byte. PICO-8 compresses the code if it is larger than a certain threshold. If compressed, the next two bytes after :c:\x00 (0x4304-0x4305) are the length of the decompressed code, stored MSB first. This is followed by two null bytes (0x4306-0x4307). The remainder (0x4308-0x7fff) is the compressed data. The decompression algorithm processes the compressed data one byte at a time, and performs an action based on the value, until the expected length of decompressed characters has been emitted: * 0x00: Copy the next byte directly to the output stream. * 0x01-0x3b: Emit a character from a lookup table: newline, space, 0123456789abcdefghijklmnopqrstuvwxyz!#%(){}[]<>+=/*:;.,~_ * 0x3c-0xff: Calculate an offset and length from this byte and the next byte, then copy those bytes from what has already been emitted. In other words, go back "offset" characters in the output stream, copy "length" characters, then paste them to the end of the output stream. Offset and length are calculated as: offset = (current_byte - 0x3c) * 16 + (next_byte & 0xf) length = (next_byte >> 4) + 2 Note that length can not be greater than offset. (Unlike typical length-offset encodings) Version ID Byte 0x8000 encodes a version ID. This appears to have changed over multiple versions of PICO-8, but the file format has not changed. Bytes 0x8001-0x8004 appear to encode a minor version or build number, as a 32-bit integer with the most significant byte first. It first became non-zero partway through version 8, and increased ever since. (Example values are 67959 and 70776) References * For a Python library that can read files in this format, see Picotool (GitHub). * Forum post by asterick describing the code compression format: http://www.lexaloffle.com/bbs/?tid=2400 * Lempel–Ziv–Welch compression